#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim: set ts=4 sw=4 noet:
#
# $Id: RegexEngine.py 2 2008-06-05 13:15:18Z wejradford $

"""
RegexEngine.py
"""

__version__ = "$Revision: 2 $"
# $URL: http://yare-gedit-plugin.googlecode.com/svn/trunk/yare/RegexEngine.py $

import re, logging

class RegexError(Exception): pass
class InvalidPatternError(RegexError): pass
class NoPatternError(RegexError): pass

class RegexEngine(object):
	"""
	Performs the find and replace.
	"""
	def __init__(self):
		"""
		Setup some intial variables.
		"""
		self.flush()

	def flush(self):
		"""
		Sets initial states.	
		"""
		self._pattern = None
		self._exp = None
		self._replacement = None
		self._isSetup = False

	def _get_replacement(self):
		return self._replacement
	replacement = property(_get_replacement, None, None, "The replacement unicode object.")

	def _get_isSetup(self):
		return self._isSetup
	isSetup = property(_get_isSetup, None, None, "True if the engine is setup.")

	def setup(self, pattern, metadata):
		"""
		Checks to see if the pattern is the same as the last time.
		Compiles the pattern.
		"""
		if not pattern:
			raise NoPatternError("Invalid pattern: %s" % pattern)
		elif pattern == self._pattern:
			return False
		try:
			self._exp = self._buildExpression(pattern, metadata)
		except re.error, e:
			self._pattern = None
			self._exp = None
			raise InvalidPatternError("Error parsing expression: %s" % e)
		self._pattern = pattern
		self._isSetup = True
		return True

	def search(self, text, replacePattern=None):
		"""
		Searches the text for the pre-compiled pattern.
		If 'replacePattern' is specified, the replacement is calculated.
		Returns the indices of the first matching text.
		Or None, None if there are no matches.
		"""
		#FIXME - Go by lines and then by slices.
		assert isinstance(text, unicode)
		match = self._exp.search(text)
		if not match:
			return None, None
		start, end = match.span()
		if replacePattern is not None:
			try:
				self._replacement = self._exp.sub(replacePattern, text[start:end], count=1)
			except re.error, e:
				raise InvalidPatternError("Error in replace expression: %s" % e)
		return start, end

	def _buildExpression(self, pattern, metadataDict):
		"""
		Returns an expression.
		"""
		flags = 0
		for flag, value in metadataDict.iteritems():
			if value:
				flags |= flag
		return re.compile(pattern, flags)

	def finditer(self, text):
		"""
		Return findIter over the text.
		"""
		assert isinstance(text, unicode)
		return self._exp.finditer(text)

	def subn(self, repl, text):
		return self._exp.subn(repl, text)

# End of $URL: http://yare-gedit-plugin.googlecode.com/svn/trunk/yare/RegexEngine.py $
